<?php

namespace app\admin\model\common;

use think\exception\ValidateException;
use think\facade\Filesystem;
use think\Image;
use think\Model;
use think\facade\Db;
use think\facade\Log;

class UploadModel extends Model
{
    protected $name = 'upload_files';
    protected $autoWriteTimestamp = 'int';
    protected $createTime = 'created_at';
    protected $updateTime = 'updated_at';
    /**
     * 上传方法
     * @param $folder_name string 存储文件夹名称
     * @param $app int 0前台用户  1后台管理员
     * @param $user_id int 上传人ID: $app参数为0时属于前台用户ID $app参数为1为管理员ID
     * @param $file string 固定值
     * @param $exts array 允许上传的文件后缀
     * @return array
     */
    public function upload($class_id=1,$folder_name='files',$app=2, $user_id=0, $file='file', $exts=[])
    {
        if( $app==2 && $user_id==0 ) {
            $token = getJWT(getHeaderToken());
            $user_id = $token['id'] ?? 0;
        }

        //允许的格式
        if( empty($exts) ) {
            $exts = ['png','jpg','jpeg','gif','bmp','doc','docx','csv','xls','xlsx','xlsm','pdf'];
        }

        validate(['image'=>'filesize:10240|fileExt:jpg|image:200,200,jpg'])
            ->check(request()->file());

        try {
            $param = request()->param();

            $file = request()->file($file);
            //文件后缀名
            $ext = $file->getOriginalExtension();
          
            $storage = 'storage';

            if( !in_array( strtolower($ext), $exts ) ) {
                return ['code'=>0,'msg'=>'格式不允许'];
            }


            //上传到本地服务器
            $savename = Filesystem::disk('public')->putFile($folder_name,$file);
            if (!$savename) {
                return ['code'=>0,'msg'=>'上传失败'];
            }
            $file_path = config('filesystem.disks.public.url') . '/'. str_replace("\\","/",$savename);
            //记录入文件表
            $extension = strtolower(pathinfo($file->getOriginalName(), PATHINFO_EXTENSION));
            $insert_data = [
                'url' => $file_path,
                'storage' => $storage,
                'cate_id' => $class_id,
                'app' => $app,
                'user_id' => $user_id,
                'file_name' => $file->getOriginalName(),
                'file_size' => $file->getSize(),
                'file_type' => 'image',
                'extension' => $extension,
                'created_at' => time()
            ];
            $insert = self::create($insert_data);
            $success = [
                'id'=>$insert['id'],
                'url'=>getBaseUrl($file_path),
                'file'=>$file_path,
                'file_name'=>$file->getOriginalName(),
                'file_size'=>$file->getSize(),
                'ext'=>$extension
            ];
            return success($success);
        } catch (ValidateException $e) {
            return fail($e->getMessage());
        }
    }

   /**
     * 根据 id 列表删除记录并同时删除服务器上的文件（无感处理，遇错记录日志）
     ** @param array $ids
     * @return bool
     */
    public function deleteByIds(array $ids): bool
    {       
        $ids = array_filter(array_unique($ids));
        if (empty($ids)) {
            return false;
        }

        Db::startTrans();
        try {
            $rows = $this->whereIn('id', $ids)->select()->toArray();
            foreach ($rows as $row) {
                $url = $row['url'] ?? '';
                if (empty($url)) {                    
                    continue;
                }
                $path = parse_url($url, PHP_URL_PATH) ?: $url;
                $filePath = public_path() . ltrim($path, '/');
                if (stripos($filePath, DIRECTORY_SEPARATOR . 'storage' . DIRECTORY_SEPARATOR) === false
                    && stripos($filePath, '/storage/') === false) {
                    Log::warning("不安全的删除请求，跳过：{$filePath}");
                    continue;
                }
                if (is_file($filePath) && file_exists($filePath)) {
                    try {
                        @unlink($filePath);
                    } catch (\Throwable $e) {
                        Log::error("删除文件失败：{$filePath}，错误：" . $e->getMessage());
                    }
                }
            }
            $this->whereIn('id', $ids)->delete();

            Db::commit();
            return true;
        } catch (\Throwable $e) {
            Db::rollback();
            Log::error('UploadModel::deleteByIds 错误：' . $e->getMessage());
            return false;
        }
    }


}